using Godot;
using System;

public partial class Army : CharacterBody2D
{
	[Export] public float Speed = 120.0f;
	[Export] public int MaxHealth = 100;
	[Export] public int AttackDamage = 20;
	[Export] public float AttackRange = 80.0f;
	[Export] public float AttackCooldown = 1.8f;
	
	private int currentHealth;
	private AnimatedSprite2D animatedSprite;
	private TextureProgressBar healthBar;
	private Area2D hurtBox;
	private Area2D attackArea;
	private CollisionShape2D attackCollision;
	private Vector2 attackAreaOffset;
	
	private Enemy targetEnemy;
	private bool isAttacking = false;
	private float attackTimer = 0.0f;
	
	public override void _Ready()
	{
		// Initialize health
		currentHealth = MaxHealth;
		
		// Get nodes
		animatedSprite = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
		healthBar = GetNode<TextureProgressBar>("HealthBar");
		hurtBox = GetNode<Area2D>("HurtBox");
		attackArea = GetNode<Area2D>("AttackArea");
		attackCollision = GetNode<CollisionShape2D>("AttackArea/CollisionShape2D");
		
		// Setup health bar
		healthBar.MaxValue = MaxHealth;
		healthBar.Value = currentHealth;
		
		// Save initial attack area offset
		attackAreaOffset = attackArea.Position;
		
		// Set attack area group
		attackArea.AddToGroup("army_attack");
		
		// Initially disable attack collision
		attackCollision.Disabled = true;
		
		// Connect signals
		hurtBox.AreaEntered += OnHurtBoxAreaEntered;
		animatedSprite.AnimationFinished += OnAnimationFinished;
		
		// Add to army group
		AddToGroup("army");
		
		// Find nearest enemy
		FindNearestEnemy();
	}
	
	public override void _PhysicsProcess(double delta)
	{
		// Update attack timer
		if (attackTimer > 0)
		{
			attackTimer -= (float)delta;
		}
		
		// Check if current target is still valid
		if (targetEnemy == null || !IsInstanceValid(targetEnemy))
		{
			FindNearestEnemy();
		}
		
		// AI behavior
		if (targetEnemy != null)
		{
			HandleAI(delta);
		}
		else
		{
			// No enemies found, stay idle
			Velocity = Vector2.Zero;
			if (animatedSprite.Animation != "idle")
			{
				animatedSprite.Play("idle");
			}
		}
	}
	
	private void FindNearestEnemy()
	{
		// Find all enemies in the scene
		var enemies = GetTree().GetNodesInGroup("enemy");
		if (enemies.Count == 0)
		{
			targetEnemy = null;
			return;
		}
		
		// Find the nearest enemy
		Enemy nearestEnemy = null;
		float nearestDistance = float.MaxValue;
		
		foreach (Node node in enemies)
		{
			if (node is Enemy enemy && IsInstanceValid(enemy))
			{
				float distance = GlobalPosition.DistanceTo(enemy.GlobalPosition);
				if (distance < nearestDistance)
				{
					nearestDistance = distance;
					nearestEnemy = enemy;
				}
			}
		}
		
		targetEnemy = nearestEnemy;
	}
	
	private void HandleAI(double delta)
	{
		// Get enemy's actual collision position
		CollisionShape2D enemyCollision = targetEnemy.GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 enemyActualPosition = targetEnemy.GlobalPosition + enemyCollision.Position;
		
		// Get army's actual collision position
		CollisionShape2D armyCollision = GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 armyActualPosition = GlobalPosition + armyCollision.Position;
		
		// Calculate actual distance between collisions
		float distanceToEnemy = armyActualPosition.DistanceTo(enemyActualPosition);
		
		// If within attack range and attack cooldown is ready
		if (distanceToEnemy <= AttackRange && attackTimer <= 0 && !isAttacking)
		{
			AttackEnemy();
		}
		else if (!isAttacking)
		{
			// Chase enemy
			ChaseEnemy();
		}
	}
	
	private void ChaseEnemy()
	{
		// Get enemy's actual collision position
		CollisionShape2D enemyCollision = targetEnemy.GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 enemyActualPosition = targetEnemy.GlobalPosition + enemyCollision.Position;
		
		// Get army's actual collision position
		CollisionShape2D armyCollision = GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 armyActualPosition = GlobalPosition + armyCollision.Position;
		
		// Calculate direction towards enemy's actual position
		Vector2 direction = (enemyActualPosition - armyActualPosition).Normalized();
		
		// Set velocity
		Velocity = direction * Speed;
		
		// Flip sprite based on movement direction
		if (direction.X > 0)
		{
			animatedSprite.FlipH = false;
		}
		else if (direction.X < 0)
		{
			animatedSprite.FlipH = true;
		}
		
		// Play run animation
		if (animatedSprite.Animation != "run")
		{
			animatedSprite.Play("run");
		}
		
		// Move
		MoveAndSlide();
	}
	
	private void AttackEnemy()
	{
		// Set attack state
		isAttacking = true;
		attackTimer = AttackCooldown;
		
		// Stop movement
		Velocity = Vector2.Zero;
		
		// Get enemy's actual collision position
		CollisionShape2D enemyCollision = targetEnemy.GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 enemyActualPosition = targetEnemy.GlobalPosition + enemyCollision.Position;
		
		// Get army's actual collision position
		CollisionShape2D armyCollision = GetNode<CollisionShape2D>("CollisionShape2D");
		Vector2 armyActualPosition = GlobalPosition + armyCollision.Position;
		
		// Face enemy's actual position
		Vector2 directionToEnemy = (enemyActualPosition - armyActualPosition).Normalized();
		if (directionToEnemy.X > 0)
		{
			animatedSprite.FlipH = false;
		}
		else if (directionToEnemy.X < 0)
		{
			animatedSprite.FlipH = true;
		}
		
		// Play attack animation
		animatedSprite.Play("attack_r1");
		
		// Adjust attack area position based on facing direction
		if (animatedSprite.FlipH)
		{
			attackArea.Position = new Vector2(-attackAreaOffset.X, attackAreaOffset.Y);
		}
		else
		{
			attackArea.Position = attackAreaOffset;
		}
		
		// Enable attack collision
		attackCollision.Disabled = false;
		
		// Auto-disable attack collision after short time
		GetTree().CreateTimer(0.3f).Timeout += () => {
			attackCollision.Disabled = true;
		};
	}
	
	private void OnHurtBoxAreaEntered(Area2D area)
	{
		// Check if it's an enemy attack area
		if (area.IsInGroup("enemy_attack"))
		{
			TakeDamage(15); // Can be modified to get damage from enemy later
		}
	}
	
	public void TakeDamage(int damage)
	{
		currentHealth -= damage;
		currentHealth = Mathf.Max(0, currentHealth);
		
		// Update health bar
		healthBar.Value = currentHealth;
		
		// Hit effect
		ShowHitEffect();
		
		// Print damage info
		GD.Print($"Army unit took {damage} damage, remaining health: {currentHealth}/{MaxHealth}");
		
		// Check if dead
		if (currentHealth <= 0)
		{
			OnDeath();
		}
	}
	
	private void ShowHitEffect()
	{
		// Create hit flash effect
		var tween = CreateTween();
		tween.SetParallel(true);
		
		// Flash effect: quickly turn red then recover
		tween.TweenProperty(animatedSprite, "modulate", new Color(1, 0.3f, 0.3f, 1), 0.1f);
		tween.TweenProperty(animatedSprite, "modulate", new Color(1, 1, 1, 1), 0.1f).SetDelay(0.1f);
	}
	
	private void OnDeath()
	{
		GD.Print("Army unit has been defeated!");
		
		// Death fade effect
		var tween = CreateTween();
		tween.TweenProperty(animatedSprite, "modulate", new Color(1, 1, 1, 0.3f), 0.2f);
		tween.TweenProperty(animatedSprite, "modulate", new Color(1, 1, 1, 0), 0.3f);
		
		// Delay removal
		GetTree().CreateTimer(0.5f).Timeout += () => {
			QueueFree();
		};
	}
	
	private void OnAnimationFinished()
	{
		// When attack animation finishes, reset attack state
		if (animatedSprite.Animation == "attack_r1")
		{
			isAttacking = false;
			// Ensure attack collision is disabled
			attackCollision.Disabled = true;
			
			// If not in attack range, continue chasing
			if (targetEnemy != null && IsInstanceValid(targetEnemy))
			{
				float distanceToEnemy = GlobalPosition.DistanceTo(targetEnemy.GlobalPosition);
				if (distanceToEnemy > AttackRange)
				{
					animatedSprite.Play("idle");
				}
			}
		}
	}
}
